package org.opens.javaskill.design.apply;

import java.util.function.Consumer;

/**
 * @Date 2020/9/9 21:45
 * @Created by 99126
 */
public class AsyncInvokeDemo {

    public static void main(String[] args) throws InterruptedException {
        AsyncFutureService futureService = new AsyncFutureService();
        AsyncFuture<String> future = futureService.submit(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "finish";
        });
        System.out.println("====== " + future.isDone());
        System.out.println("future result " + future.get());
        System.out.println("====== " + future.isDone());

        futureService.submit(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "finish";
        }, x -> {
            System.out.println("异步结果 " + x);
        });
        System.out.println("======");
    }

}

interface AsyncFuture<T> {

    T get() throws InterruptedException;

    boolean isDone();

}

/**
 * 说明:
 *      1. 这个是多线程所执行的任务封装, 就像Runnable或者Callable一样.
 */
@FunctionalInterface
interface AsyncFutureTask<T> {

    T call();

}

/**
 * 说明:
 *      1. 这个类相当于是异步方法结果的封装.
 */
class AsyncFutureImpl<T> implements AsyncFuture<T> {

    private volatile boolean done = false;

    private T result;

    @Override
    public boolean isDone() {
        return done;
    }

    public void done(T result) {
        synchronized (this) {
            this.result = result;
            this.done = true;
            this.notifyAll();
        }
    }

    @Override
    public T get() throws InterruptedException {
        synchronized (this) {
            while (!done) {
                this.wait();
            }
        }
        return result;
    }
}

/**
 * 说明:
 *      1. 这个类相当于是{@link AsyncFutureTask}和{@link AsyncFuture}这两个类之间的桥接者, 用来分离任务与执行者之间的紧密耦合, 达到降
 *      低程序耦合的作用.
 */
class AsyncFutureService {

    /**
     * 说明:
     *      1. 这种方式相当于是返回一个Future对象, 而这个Future对象的get方法会使调用它的线程进入阻塞.
     */
    public <T> AsyncFuture<T> submit(final AsyncFutureTask<T> task) {
        AsyncFutureImpl<T> future = new AsyncFutureImpl<>();
        new Thread(() -> {
            T result = task.call();
            future.done(result);
        }).start();
        return future;
    }

    /**
     * 说明:
     *      1. 这种是更加高级的方式, 设置回调, 待线程处理完成之后, 会自动调用传入的函数处理结果;
     *      2. 这种方式不需要调用Future对象的get方法, 只需要传入对应的回调方法即刻, 所以主线程不会陷入阻塞.
     */
    public <T> AsyncFuture<T> submit(final AsyncFutureTask<T> task, final Consumer<T> consumer) {
        AsyncFutureImpl<T> future = new AsyncFutureImpl<>();
        new Thread(() -> {
            T result = task.call();
            future.done(result);
            consumer.accept(result);
        }).start();
        return future;
    }

}